#include "data_miner.h"

list<boost::shared_ptr<music::title_dataset> > music::data_miner::
create_datasets(const list<boost::shared_ptr<music::title_adapter> > &l)
{
	list<boost::shared_ptr<music::title_dataset> > rtrn;
	typedef list<boost::shared_ptr<music::title_adapter> >::
		const_iterator it;
	int dur = 0;
	boost::shared_ptr<music::title_dataset> ds(
		new music::title_dataset());
	for(it i = l.begin(); i != l.end(); ++i) {
		if(dur >= 1200) {
			dur = 0;
			rtrn.push_back(ds);
			ds.reset(new music::title_dataset());
		}
		ds->push_back(*i);
		dur += (*i)->get()->get_duration();
	}
	if(!ds->empty()) {
		rtrn.push_back(ds);
	}
	return rtrn;
}

list<boost::shared_ptr<music::title_adapter> > music::data_miner::
	create_list(const list<string> &l) 
{
	list<boost::shared_ptr<music::title_adapter> > rtrn;
	for(list<string>::const_iterator i = l.begin(); i != l.end(); ++i) {
		music::file_streamer streamer(*i);
		list<boost::shared_ptr<model::title> > tmp=streamer.read_file();
		cout << "in streamer file: " << tmp.size() << endl;
		typedef list<boost::shared_ptr<model::title> >::
			reverse_iterator it;
		int num = 0;
		boost::shared_ptr<model::title> prev;
		for(it j = tmp.rbegin(); 
		    j != tmp.rend() && num < 50; ++j,++num) {
			if(prev.get() == 0 || 
			   (prev->get_title() != (*j)->get_title())) {
				rtrn.push_back(
				boost::shared_ptr<music::title_adapter>(
					new music::title_adapter(*j)));
			}
			prev = (*j);
		}
	}
	return rtrn;
}

void music::data_miner::doit()
{
	music::file_streamer streamer(_client->get_name() + ".txt");
	list<string> files = streamer.list_files();
	cout << "streamer file: " << files.size() << endl;
	// building a list with all titles
	list<boost::shared_ptr<music::title_adapter> > titles = 
		create_list(files);
	cout << "titles: " << titles.size() << endl;
	list<boost::shared_ptr<music::title_dataset> > datasets = 
		create_datasets(titles);
	int support = int(datasets.size() * 0.01);
	cout << "datasets: " << datasets.size() << 
		"support: " << support << endl;
	music::data_miner::my_apriori apr(
		datasets, (support <= 1) ? 2 : support, 0.2); 
	apr.doit();

	typedef my_apriori::t_item result_t;
	list<result_t> &lst = apr.get_result();
	cout << "results: " << lst.size() << endl;
	// now we are normalizing the results in one single list
	typedef my_apriori::t_itemset_c::data_ptr data_ptr;
	list<data_ptr> items;
	typedef list<result_t>::iterator itr;
	typedef list<data_ptr>::iterator itr2;
	for(itr i = lst.begin(); i != lst.end(); ++i) {
		cout << (*i) << endl;
		for(itr2 j = (*i).get_items().begin(); 
		    j != (*i).get_items().end(); ++j) {
			items.push_back(*j);
		}
	}

	if(items.empty()) { // sorry, the algorithm has failed
		cout << "sorry, the algorithm has failed..." << endl;
		return;
	}
	cout << "size of items: " <<  items.size() << endl;
	// now check if all titles are available on the client...

	for(list<data_ptr>::iterator i = items.begin(); i != items.end(); ++i) {
		model::title *t = 
		 _model->find_title((*i)->get()->get_filename(), _client.get());
		if(t == 0) {
			items.erase(i++);
		}
	}
	cout << "size of items after check: " <<  items.size() << endl;

	// now choose one random item
	int x = (rand() % items.size());
	int cnt = 0;
	itr2 iter;
	for(iter = items.begin(); (iter != items.end()) && (cnt < x);
		++iter,++cnt);
	
	_result = (*iter)->get();
}

